package cn.yunyichina.provider.pay.service.impl;

import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.WechatPayService;
import cn.yunyichina.provider.framework.exception.CallException;
import cn.yunyichina.provider.framework.qiniu.QiniuService;
import cn.yunyichina.provider.framework.utils.HttpUtils;
import cn.yunyichina.provider.framework.utils.UUIDUtil;
import cn.yunyichina.provider.iface.entity.base.EventVo;
import cn.yunyichina.provider.iface.entity.base.LogVo;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.provider.pay.config.Alipay;
import cn.yunyichina.provider.pay.config.Config;
import cn.yunyichina.provider.pay.constant.MethodRouter;
import cn.yunyichina.provider.pay.dao.OrderCheckedExceptionDao;
import cn.yunyichina.provider.pay.dao.PaymentCheckSourceFileDao;
import cn.yunyichina.provider.pay.entity.OrderCheckedException;
import cn.yunyichina.provider.pay.entity.PaymentCheckSourceFile;
import cn.yunyichina.provider.pay.service.WechatPaymentService;
import cn.yunyichina.provider.pay.utils.WechatCSVFileUtil;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 微信对账单解析入库
 * Created by JoeZ on 2016/10/19.
 */
@Service
public class WechatPaymentServiceImpl implements WechatPaymentService {

    @Resource
    private PaymentCheckSourceFileDao paymentCheckSourceFileDao;

    @Resource
    private OrderCheckedExceptionDao orderCheckedExceptionDao;

    @Resource
    private Properties yaml;

    private static Logger logger = LoggerFactory.getLogger(WechatPaymentServiceImpl.class);

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    SimpleDateFormat YYYYMMDDHHMISS14 = new SimpleDateFormat("yyyYMMddHHmmss");

    /**
     * 解析本地微信对账文件
     * @interface
     * @param json
     * @return stop_finance_flag 是否需要停止对账,full_success是否完全成功,count成功入库的记录数,import_full_success导入是否成功
     */
    @Override
	public Response getWechatPayment(String json) {
        logger.info("WechatPaymentServiceImpl.getWechatPayment json-->" + JsonUtils.toJsonString(json));
        JSONObject mapReturn = new JSONObject();
        JSONObject jsonMap = JsonUtils.parseObject(json);

        String appId = jsonMap.getString("appId");
        String hospitalId = jsonMap.getString("orgId");
        String hospitalName = jsonMap.getString("orgName");
        String tag = jsonMap.getString("tag");
        String date = jsonMap.getString("date");
        
        //是否记录系统日志
    	boolean saveLogFlag = false;
    	LogVo log = new LogVo();
		log.setOrgId(hospitalId);
		log.setOrgName(hospitalName);
		
		boolean importFullSuccess = false;
        boolean saveDbSuccess = false;
        String message = "";

        //调用weichat子系统
        Response response = WechatPayService.callHumpFromInternal(MethodRouter.WECHAT_DOWNLOAD_FILE_PATH, JSON.toJSONString(jsonMap));
        logger.info("WechatPaymentServiceImpl.getWechatPayment 下载对wechat账单返回内容-->" + JsonUtils.toJsonString(response));
        if ("0".equals(response.getResultCode())) {
            if (!"FAIL".equals(response.getResultCode())) {
                Map<String, String> resMap = JSONObject.parseObject(response.getResult() , Map.class);
                String fileName = resMap.get("fileName");
                String insFileName = resMap.get("insFileName");
                Boolean flag = qiniuDownloadSave(fileName, hospitalName);
                Boolean insFlag = false;
                if(StringUtils.isNotBlank(insFileName)){
                    insFlag = qiniuDownloadSave(insFileName, hospitalName);
                }
                logger.info("flag:" + flag +",insFlag:" + insFlag);
                if (flag || insFlag) {
                    try {
                        if(flag){
                            String filePath = yaml.getProperty(Config.CONFIG_PAY_WECHAT_CHECK_ACCOUNT_PATH) + fileName;
                            mapReturn = paymentCheckSourceBillFileDataSave(filePath, hospitalId, hospitalName, appId, tag);
                        }

                        if(insFlag){
                            String filePath = yaml.getProperty(Config.CONFIG_PAY_WECHAT_CHECK_ACCOUNT_PATH) + insFileName;
                            if(mapReturn.isEmpty()){
                                mapReturn = paymentCheckSourceBillFileDataSave(filePath, hospitalId, hospitalName, appId);
                            }else{
                                paymentCheckSourceBillFileDataSave(filePath, hospitalId, hospitalName, appId);
                            }
                        }

                        mapReturn.remove("list");
                        logger.info("WechatPaymentServiceImpl.getWechatPayment 对账单入库返回mapReturn-->" + JsonUtils.toJsonString(mapReturn));
                        if (mapReturn.containsKey("import_full_success") && mapReturn.getBooleanValue("import_full_success")) {
                            message = "导入第三方数据成功";
                            importFullSuccess = true;
                        }
                        else if (mapReturn.containsKey("import_full_success") && mapReturn.getBooleanValue("import_full_success") == false) {
                            message = "导入第三方数据存在异常";
                            importFullSuccess = false;
                        }
                        if (mapReturn.containsKey("stop_finance_flag") && mapReturn.getBooleanValue("stop_finance_flag")) {
                            message += " 订单号 不存在，终止对账";

                            log.setContent(message);
                            saveLogFlag = true;
                        }
                        if ( ! mapReturn.containsKey("count")) {
                            message += " 没有执行入库操作,可能存在异常，或没有可入库的数据";
                            saveDbSuccess = false;
                        }
                        else if (mapReturn.containsKey("count") && mapReturn.getIntValue("count") == 0) {
                            message += " 第三方数据入库失败";
                            saveDbSuccess = false;

                            log.setContent(message);
                            saveLogFlag = true;
                        }
                        else if (mapReturn.containsKey("count") && mapReturn.getIntValue("count") > 0) {
                            message += " 第三方数据入库成功";
                            log.setContent(message);
                            saveDbSuccess = true;

                        }

                        if (mapReturn.containsKey("exception_flag") && mapReturn.getBooleanValue("exception_flag")) {
                            log.setContent("处理过程发生异常");
                            saveLogFlag = true;
                        }

                        String resultCode = "-1";
                        if (importFullSuccess && saveDbSuccess) {
                            message = "导入和处理数据成功";
                            resultCode = "0";
                        }
                        mapReturn.put("message", message);
                        response.setResultCodeAndMessageAndResult(resultCode , message, JsonUtils.toJsonString(mapReturn));

                    } catch (Exception e) {
                        logger.error("数据导入或入库异常[WechatPaymentCheckSourceFileServiceImpl.checkLocalFile]", e);
                        log.setContent("数据导入或入库异常");
                        saveLogFlag = true;
                        response.setResultCodeAndMessage("-1", "数据导入或入库异常");
                    }
                } else {
                    logger.info("下载七牛数据异常---Http download Qiuniu fail..hospitalName:" + hospitalName + " and appId:" + appId);
                    log.setContent("下载七牛数据异常");
                    response.setResultCodeAndMessage("-1", "下载七牛数据异常");
                    saveLogFlag = true;
                }
            }
            else {
            	logger.error("获取第三方数据的文件名为空");
            	response.setResultCodeAndMessage("-1", "获取第三方数据的文件名为空");
            	log.setContent("获取第三方数据的文件名为空");
        		saveLogFlag = true;
            }

        } else if ("FAIL".equals(response.getResultCode()) && "No Bill Exist".equals(response.getResultMessage())) {
            response.setResultCodeAndMessage("51001" , response.getResultMessage() + " 微信账单不存在");
            log.setContent("微信账单不存在"+response.getResultMessage() + " 支付宝账单不存在");
            importFullSuccess=true;
            saveDbSuccess=true;
    		//saveLogFlag = true;
        } else {
            response.setResultCodeAndMessage(Response.FAILURE_CODE , response.getResultMessage());
            log.setContent("文件下载异常："+response.getResultMessage());
    		saveLogFlag = true;
        }
        
        mapReturn.put("data_source", "微信");

        if (importFullSuccess && saveDbSuccess) {
        	mapReturn.put("full_success", true);
        }
        else {
        	mapReturn.put("full_success", false);
        	Map<String,Object> paramEvent = new HashMap<>();
        	paramEvent.put("event_code", "CK_PULL_PAY_BILL");
        	paramEvent.put("module_code", "CHECK_ACCOUNT");
        	Response responseEvent = BaseService.callHumpFromInternal("yyt.base.event.get", JsonUtils.toJsonString(paramEvent));
        	if (StringUtils.isNotBlank(responseEvent.getResult())) {
        		EventVo event = JsonUtils.parseObject(responseEvent.getResult(), EventVo.class);
        		FinanceServiceImpl.sendSmsForFail(hospitalId,"CK_PULL_PAY_BILL",hospitalName, date, YYYYMMDDHHMISS14.format(new Date()),event.getEventLevel()+"",message);
        	}
        	else {
        		logger.error("获取系统事件定义事事件，无法获取事件级别：CK_PULL_PAY_BILL");
        		FinanceServiceImpl.sendSmsForFail(hospitalId,"CK_PULL_PAY_BILL",hospitalName, date, YYYYMMDDHHMISS14.format(new Date()),"-1","支付宝："+message);
        	}
        	
        	//记录系统日志
            if (saveLogFlag) {
            	FinanceServiceImpl.insertLog(hospitalId,"CK_PULL_PAY_BILL",JsonUtils.toJsonString(mapReturn));
            }
        	
        }
        return response;
    }

    /**
     *  微信自费账单入库 List<PaymentCheckSourceFile>,stop_finance_flag 是否需要停止对账,import_full_success是否完全成功,count成功入库的记录数
     */
    @Override
    public JSONObject paymentCheckSourceBillFileDataSave(String filePath, String hospitalId, String hospitalName, String appId , String tag) throws Exception {
        JSONObject mapReturn = new JSONObject();
        try {
            List<PaymentCheckSourceFile> payDatas = null;
            if(StringUtils.isNotBlank(tag)){
            	mapReturn = wechatPartyimportBills(filePath, hospitalId, hospitalName, appId);
            }else{
            	mapReturn = autoWechatPartyimportBills(filePath, hospitalId, hospitalName, appId);
            }
            
            logger.info(JsonUtils.toJsonString(mapReturn));
        	payDatas = (List<PaymentCheckSourceFile>) mapReturn.get("list");
        	
        	if (mapReturn.containsKey("stop_finance_flag") && mapReturn.getBooleanValue("stop_finance_flag")) {
        		logger.info("终止对账，入库操作取消");
        	}
        	else {
        		if (payDatas.size() > 0) {
                    int i = addSourceFile(payDatas, hospitalId , hospitalName);
                    mapReturn.put("resultCode", "0");
                    mapReturn.put("resultMessage", "入库成功！");
                    mapReturn.put("count", String.valueOf(i));

                } else {
                	mapReturn.put("resultCode", "5001");
                	mapReturn.put("resultMessage", "入库失败..对账文件解析失败.");
                	logger.error("没有处理成功的对账记录" + hospitalName);
                }
        	}
        	
            
        } catch (Exception e) {
        	logger.error("账单入库失败", e);
            mapReturn.put("exception_flag", true);
            mapReturn.put("resultCode", "5001");
            mapReturn.put("resultMessage", e.getMessage());
        }
        return mapReturn;
    }



    /**
     *  微信医保账单入库
     */
    public JSONObject paymentCheckSourceBillFileDataSave(String filePath, String hospitalId, String hospitalName, String appId){
        JSONObject mapReturn = new JSONObject();
        try {
            List<PaymentCheckSourceFile> payDatas = null;
            mapReturn = wechatPartyimportInsBills(filePath, hospitalId, hospitalName, appId);

            logger.info("微信医保账单入库 paymentCheckSourceBillFileDataSave:" + JsonUtils.toJsonString(mapReturn));
            payDatas = (List<PaymentCheckSourceFile>) mapReturn.get("list");

            if (mapReturn.containsKey("stop_finance_flag") && mapReturn.getBooleanValue("stop_finance_flag")) {
                logger.info("医保账单终止对账，入库操作取消");
            }
            else {
                if (payDatas.size() > 0) {
                    int i = addSourceFile(payDatas, hospitalId, hospitalName);
                    mapReturn.put("resultCode", "0");
                    mapReturn.put("resultMessage", hospitalName + "_医保账单入库成功！");
                    mapReturn.put("count", String.valueOf(i));

                } else {
                    mapReturn.put("resultCode", "5001");
                    mapReturn.put("resultMessage", hospitalName +"_医保账单入库失败..对账文件解析失败.");
                    logger.error("没有处理成功的对账记录" + hospitalName);
                }
            }


        } catch (Exception e) {
            logger.error(hospitalName + "_医保账单入库失败", e);
            mapReturn.put("exception_flag", true);
            mapReturn.put("resultCode", "5001");
            mapReturn.put("resultMessage", e.getMessage());
        }
        return mapReturn;
    }


    /**
     * 微信对账文件解析(手动)
     *
     * @param filePath
     * @param hospitalId
     * @param hospitalName
     * @return List<PaymentCheckSourceFile>,stop_finance_flag 是否需要停止对账,import_full_success是否完全成功
     */
    public JSONObject wechatPartyimportBills(String filePath, String hospitalId, String hospitalName, String appId) throws Exception {

        List<PaymentCheckSourceFile> sourceList = null;
        JSONObject mapReturn = new JSONObject();
        mapReturn.put("hospital_name", hospitalName);
        mapReturn.put("hospital_id", hospitalId);
        mapReturn.put("app_id", appId);
        mapReturn.put("file_path", filePath);
        mapReturn.put("stop_finance_flag", false);
        boolean importFullSuccess = false;
        sourceList = new ArrayList();
        if (StringUtils.isNotBlank(filePath)) {

            sourceList = new ArrayList();
            try {
                WechatCSVFileUtil wechatCSVFileUtil = new WechatCSVFileUtil(filePath);
                List<List<String>> csvDatas = wechatCSVFileUtil.weichatReadCSVFile();
                for (List<String> vs : csvDatas) {
                    List<String> datas = new ArrayList<>();
                    for (int i = 0; i < vs.size(); i++) {
                        String reStr = vs.get(i).replace("\"", "");
                        datas.add(reStr);
                    }
                    if ("SUCCESS".equals(datas.get(9)) || ("REFUND".equals(datas.get(9)) && "SUCCESS".equals(datas.get(19)))|| ("REFUND".equals(datas.get(9)) && "PROCESSING".equals(datas.get(19)))|| ("REVOKED".equals(datas.get(9)) && "PROCESSING".equals(datas.get(19)))) {

                        PaymentCheckSourceFile paymentCheckSourceFile = new PaymentCheckSourceFile();

                        //根据orgId、orderNo查询，platformId、platformName
                        Map<String, String> map = new HashMap<String, String>();
                        map.put("order_no", datas.get(6));
                        Response response = BaseService.callHumpFromInternal(MethodRouter.BASE_FIND_ORDER, JSON.toJSONString(map));
                        if ("0".equals(response.getResultCode())) {
                            map = JsonUtils.parseObject(response.getResult(), Map.class);
                            paymentCheckSourceFile.setPlatformId(map.get("platform_id"));
                            paymentCheckSourceFile.setPlatformName(map.get("platform_name"));
                            paymentCheckSourceFile.setPlatformCode(map.get("platform_code"));
                            paymentCheckSourceFile.setPlatformOrgAppCode(map.get("platform_org_app_code"));
                            paymentCheckSourceFile.setPlatformOrgAppName(map.get("platform_org_app_name"));
                            paymentCheckSourceFile.setOrgId(map.get("org_id"));
                            paymentCheckSourceFile.setOrgName(map.get("org_name"));
                            paymentCheckSourceFile.setOrgCode(map.get("org_code"));
                        } else {
                            //异常订单录入
                            OrderCheckedException orderException = new OrderCheckedException();
                            orderException.setId(UUIDUtil.get32UUID());
                            orderException.setOrderNo(datas.get(6));
                            orderException.setOrgId(hospitalId);
                            orderException.setPayAppId(appId);
                            orderException.setPayTime(StringUtils.isBlank(datas.get(3)) ? null : datas.get(0));
                            orderException.setExceptionType((short) 1);
                            orderException.setExceptionReason(hospitalName + " 订单号：" + datas.get(6) + " 订单不存在！！");
                            orderException.setCreatedBy("三方对账平台");
                            orderException.setCreatedTime(sdf.format(new Date()));

                            orderCheckedExceptionDao.insert(orderException);
                            logger.error(hospitalName + " 订单号：" + datas.get(6) + " 订单不存在！！");
                            
                            mapReturn.put("stop_finance_flag", true);
                            throw new CallException("-1","平台没有订单，终止对账，orderNo="+datas.get(1));
                        }

                        paymentCheckSourceFile.setId(UUIDUtil.get32UUID());
                        paymentCheckSourceFile.setPayAppId(appId);
                        paymentCheckSourceFile.setPayTime(StringUtils.isBlank(datas.get(3)) ? null : datas.get(0));
                        paymentCheckSourceFile.setOrderNo(datas.get(6));

                        //过滤交易状态 如果是REFUND 只保存退款成功流水号、订单号
                        if ("SUCCESS".equals(datas.get(9))) {
                            paymentCheckSourceFile.setPaymentDealId(datas.get(5));
                            paymentCheckSourceFile.setPayAmount(parseAmount(datas.get(12)));
                        } else if ("REFUND".equals(datas.get(9)) || "REVOKED".equals(datas.get(9))) {
                            paymentCheckSourceFile.setPaymentDealId(datas.get(14));
                            paymentCheckSourceFile.setPayAmount(parseAmount(datas.get(16)));
                        }

                        paymentCheckSourceFile.setAccountAmount(0);
                        paymentCheckSourceFile.setMedicareAmount(0);
                        paymentCheckSourceFile.setInsuranceAmount(0);
                        paymentCheckSourceFile.setTotalAmount(paymentCheckSourceFile.getInsuranceAmount() + paymentCheckSourceFile.getPayAmount());
                        paymentCheckSourceFile.setDescription(datas.get(21));
                        paymentCheckSourceFile.setAccountName(datas.get(7));
                        paymentCheckSourceFile.setPayTypeDesc(datas.get(8));
                        paymentCheckSourceFile.setPayStatusDesc(datas.get(9));
                        paymentCheckSourceFile.setPayStatus(parsePayStatus(datas.get(13), datas.get(9)));
                        paymentCheckSourceFile.setGoodsName(datas.get(20));
                        paymentCheckSourceFile.setServiceFee(parseAmount(datas.get(22)));
                        paymentCheckSourceFile.setFeeRate(Double.valueOf(datas.get(23).replace("%", "")));
                        paymentCheckSourceFile.setPayMode((short) 1);
                        paymentCheckSourceFile.setImportTime(sdf.format(new Date()));
                        paymentCheckSourceFile.setUpdateTime(sdf.format(new Date()));
                        paymentCheckSourceFile.setCreatedTime(StringUtils.isBlank(datas.get(3)) ? null : datas.get(0));

                        sourceList.add(paymentCheckSourceFile);
                    }
                }
                importFullSuccess = true;
            } 
            catch (CallException ce) {
            	importFullSuccess = false;
            }
            catch (Exception e) {
            	importFullSuccess = false;
                logger.error("wechatPartyimportBills:[第三方账单读取失败]", e);
                mapReturn.put("exception_flag", true);
               
            }
        }
        mapReturn.put("import_full_success", importFullSuccess);
        mapReturn.put("list", sourceList);
        return mapReturn;
    }


    /**
     * 微信对账文件解析(自动)
     *
     * @param filePath
     * @param hospitalId
     * @param hospitalName
     * @return list List<PaymentCheckSourceFile>,stop_finance_flag 是否需要停止对账,import_full_success是否完全成功
     */
    public JSONObject autoWechatPartyimportBills(String filePath, String hospitalId, String hospitalName, String appId) throws Exception {

        List<PaymentCheckSourceFile> sourceList = null;
        JSONObject mapReturn = new JSONObject();
        mapReturn.put("hospital_name", hospitalName);
        mapReturn.put("hospital_id", hospitalId);
        mapReturn.put("app_id", appId);
        mapReturn.put("file_path", filePath);
        mapReturn.put("stop_finance_flag", false);
        boolean importFullSuccess = false;//数据是否全部读取完成
        sourceList = new ArrayList();
        if (StringUtils.isNotBlank(filePath)) {

            sourceList = new ArrayList();
            try {
                WechatCSVFileUtil wechatCSVFileUtil = new WechatCSVFileUtil(filePath);
                List<List<String>> csvDatas = wechatCSVFileUtil.weichatReadCSVFile();

                long beginTime = new Date().getTime() / 1000;
                logger.info("<<<<< wechatPartyimportBills.beginTime:" + beginTime);

                for (List<String> vs : csvDatas) {
                    List<String> datas = new ArrayList<>();
                    for (int i = 0; i < vs.size(); i++) {
                        String reStr = vs.get(i).replace("\"", "");
                        datas.add(reStr);
                    }
                    if ("SUCCESS".equals(datas.get(9)) || ("REFUND".equals(datas.get(9)) && "SUCCESS".equals(datas.get(19))) || ("REFUND".equals(datas.get(9)) && "PROCESSING".equals(datas.get(19)))|| ("REVOKED".equals(datas.get(9)) && "PROCESSING".equals(datas.get(19)))) {

                        PaymentCheckSourceFile paymentCheckSourceFile = new PaymentCheckSourceFile();

                        paymentCheckSourceFile.setOrgId(hospitalId);
                        paymentCheckSourceFile.setOrgName(hospitalName);
                        paymentCheckSourceFile.setId(UUIDUtil.get32UUID());
                        paymentCheckSourceFile.setPayAppId(appId);
                        paymentCheckSourceFile.setPayTime(StringUtils.isBlank(datas.get(3)) ? null : datas.get(0));
                        paymentCheckSourceFile.setOrderNo(datas.get(6));

                        //过滤交易状态 如果是REFUND 只保存退款成功流水号、订单号
                        if ("SUCCESS".equals(datas.get(9))) {
                            paymentCheckSourceFile.setPaymentDealId(datas.get(5));
                            paymentCheckSourceFile.setPayAmount(parseAmount(datas.get(12)));
                        } else if ("REFUND".equals(datas.get(9)) || "REVOKED".equals(datas.get(9))) {
                            paymentCheckSourceFile.setPaymentDealId(datas.get(14));
                            paymentCheckSourceFile.setPayAmount(parseAmount(datas.get(16)));
                        }

                        paymentCheckSourceFile.setAccountAmount(0);
                        paymentCheckSourceFile.setMedicareAmount(0);
                        paymentCheckSourceFile.setInsuranceAmount(0);
                        paymentCheckSourceFile.setTotalAmount(paymentCheckSourceFile.getInsuranceAmount() + paymentCheckSourceFile.getPayAmount());
                        paymentCheckSourceFile.setDescription(datas.get(21));
                        paymentCheckSourceFile.setAccountName(datas.get(7));
                        paymentCheckSourceFile.setPayTypeDesc(datas.get(8));
                        paymentCheckSourceFile.setPayStatusDesc(datas.get(9));
                        paymentCheckSourceFile.setPayStatus(parsePayStatus(datas.get(13), datas.get(9)));
                        paymentCheckSourceFile.setGoodsName(datas.get(20));
                        paymentCheckSourceFile.setServiceFee(parseAmount(datas.get(22)));
                        paymentCheckSourceFile.setFeeRate(Double.valueOf(datas.get(23).replace("%", "")));
                        paymentCheckSourceFile.setPayMode((short) 1);
                        paymentCheckSourceFile.setImportTime(sdf.format(new Date()));
                        paymentCheckSourceFile.setUpdateTime(sdf.format(new Date()));
                        paymentCheckSourceFile.setCreatedTime(StringUtils.isBlank(datas.get(3)) ? null : datas.get(0));

                        sourceList.add(paymentCheckSourceFile);
                    }
                }

                logger.info("<<<<< wechatPartyimportBills.endTime:" + ((new Date().getTime() / 1000) - beginTime));
                importFullSuccess = true;
            } catch (IOException e) {
            	mapReturn.put("exception_flag", true);
                logger.error("autoWechatPartyimportBills:[第三方账单读取失败]", e);
                importFullSuccess = false;
            }
        }
        logger.info(hospitalName +"_微信自费对账单获取成功解析笔数：" + sourceList.size() + ",appId:" + appId);
        mapReturn.put("import_full_success", importFullSuccess);
        mapReturn.put("list", sourceList);
        return mapReturn;
    }



    /**
     * 微信医保对账文件解析
     *
     * @param filePath
     * @param hospitalId
     * @param hospitalName
     */
    public JSONObject wechatPartyimportInsBills(String filePath, String hospitalId, String hospitalName, String appId) throws Exception {

        List<PaymentCheckSourceFile> sourceList = null;
        JSONObject mapReturn = new JSONObject();
        mapReturn.put("hospital_name", hospitalName);
        mapReturn.put("hospital_id", hospitalId);
        mapReturn.put("app_id", appId);
        mapReturn.put("file_path", filePath);
        mapReturn.put("stop_finance_flag", false);
        boolean importFullSuccess = false;
        sourceList = new ArrayList();
        if (StringUtils.isNotBlank(filePath)) {

            sourceList = new ArrayList();
            try {
                WechatCSVFileUtil wechatCSVFileUtil = new WechatCSVFileUtil(filePath);
                List<List<String>> csvDatas = wechatCSVFileUtil.weichatReadCSVFile();
                for (List<String> vs : csvDatas) {
                    if(vs.size() < 2){
                        continue;
                    }
                    List<String> datas = new ArrayList<>();
                    for (int i = 0; i < vs.size(); i++) {
                        String reStr = vs.get(i).replace("\"", "");
                        datas.add(reStr);
                    }

                    //获取账单信息
                    String orderNo = datas.get(42);
                    String payStatus = datas.get(45);
                    String refundStatus = datas.get(19);

                    if ("SUCCESS".equals(payStatus) || ("REFUND".equals(payStatus) && "SUCCESS".equals(refundStatus))|| ("REFUND".equals(payStatus) && "PROCESSING".equals(refundStatus))|| ("REVOKED".equals(payStatus) && "PROCESSING".equals(refundStatus))) {

                        PaymentCheckSourceFile paymentCheckSourceFile = new PaymentCheckSourceFile();

                        //根据orgId、orderNo查询，platformId、platformName
                        Map<String, String> map = new HashMap<String, String>();
                        map.put("order_no", orderNo);
                        Response response = BaseService.callHumpFromInternal(MethodRouter.BASE_FIND_ORDER, JSON.toJSONString(map));
                        if ("0".equals(response.getResultCode())) {
                            map = JsonUtils.parseObject(response.getResult(), Map.class);
                            paymentCheckSourceFile.setPlatformId(map.get("platform_id"));
                            paymentCheckSourceFile.setPlatformName(map.get("platform_name"));
                            paymentCheckSourceFile.setPlatformCode(map.get("platform_code"));
                            paymentCheckSourceFile.setPlatformOrgAppCode(map.get("platform_org_app_code"));
                            paymentCheckSourceFile.setPlatformOrgAppName(map.get("platform_org_app_name"));
                            paymentCheckSourceFile.setOrgId(map.get("org_id"));
                            paymentCheckSourceFile.setOrgName(map.get("org_name"));
                            paymentCheckSourceFile.setOrgCode(map.get("org_code"));
                        } else {
                            //异常订单录入
                            OrderCheckedException orderException = new OrderCheckedException();
                            orderException.setId(UUIDUtil.get32UUID());
                            orderException.setOrderNo(orderNo);
                            orderException.setOrgId(hospitalId);
                            orderException.setPayAppId(appId);
                            orderException.setPayTime(datas.get(0));
                            orderException.setExceptionType((short) 1);
                            orderException.setExceptionReason(hospitalName + " 订单号：" + orderNo + " 订单不存在！！");
                            orderException.setCreatedBy("三方对账平台");
                            orderException.setCreatedTime(sdf.format(new Date()));

                            orderCheckedExceptionDao.insert(orderException);
                            logger.error(hospitalName + " 订单号：" + orderNo + " 订单不存在！！");

                            mapReturn.put("stop_finance_flag", true);
                            throw new CallException("-1",hospitalName+"_平台没有医保订单，终止对账，orderNo=" + orderNo);
                        }

                        paymentCheckSourceFile.setId(UUIDUtil.get32UUID());
                        paymentCheckSourceFile.setPayAppId(appId);
                        paymentCheckSourceFile.setPayTime(datas.get(0));
                        paymentCheckSourceFile.setOrderNo(orderNo);

                        //过滤交易状态 如果是REFUND 只保存退款成功流水号、订单号
                        if ("SUCCESS".equals(payStatus)) {
                            paymentCheckSourceFile.setPaymentDealId(datas.get(5));
                            paymentCheckSourceFile.setPayAmount(parseAmount(datas.get(46)));
                        } else if ("REFUND".equals(payStatus)) {
                            paymentCheckSourceFile.setPaymentDealId(datas.get(14));
                            paymentCheckSourceFile.setPayAmount(parseAmount(datas.get(16)));
                        }

                        paymentCheckSourceFile.setAccountAmount(parseAmount(datas.get(47)));
                        paymentCheckSourceFile.setMedicareAmount(0);
                        paymentCheckSourceFile.setInsuranceAmount(parseAmount(datas.get(47)) + 0);
                        paymentCheckSourceFile.setTotalAmount(paymentCheckSourceFile.getPayAmount() + paymentCheckSourceFile.getInsuranceAmount());
                        paymentCheckSourceFile.setDescription(datas.get(21));
                        paymentCheckSourceFile.setAccountName(datas.get(7));
                        paymentCheckSourceFile.setPayTypeDesc(datas.get(8) + "_INS");
                        paymentCheckSourceFile.setPayStatusDesc(payStatus);
                        paymentCheckSourceFile.setPayStatus(parsePayStatus(null, payStatus));
                        paymentCheckSourceFile.setGoodsName(datas.get(20));
                        paymentCheckSourceFile.setServiceFee(StringUtils.isNotBlank(datas.get(22)) ? parseAmount(datas.get(22)) : 0);
                        paymentCheckSourceFile.setFeeRate(StringUtils.isNotBlank(datas.get(23)) ?Double.valueOf(datas.get(23).replace("%", "")) : 0);
                        paymentCheckSourceFile.setPayMode((short) 1);
                        paymentCheckSourceFile.setImportTime(sdf.format(new Date()));
                        paymentCheckSourceFile.setUpdateTime(sdf.format(new Date()));
                        paymentCheckSourceFile.setCreatedTime(datas.get(0));

                        sourceList.add(paymentCheckSourceFile);
                    }
                }
                importFullSuccess = true;
            }
            catch (CallException ce) {
                importFullSuccess = false;
            }
            catch (Exception e) {
                importFullSuccess = false;
                logger.error("wechatPartyimportBills:[第三方账单读取失败]", e);
                mapReturn.put("exception_flag", true);

            }
        }
        mapReturn.put("import_full_success", importFullSuccess);
        mapReturn.put("list", sourceList);
        return mapReturn;
    }

    /**
     * 解析交易状态
     *
     * @param payStatus
     * @return
     */
    public Short parsePayStatus(String status, String payStatus) {
        int ps = 0;
        if ("SUCCESS".equals(payStatus)) {
            ps = 1;
        } else if ("REFUND".equals(payStatus)) {
            ps = 2;
        }
        return (short) ps;
    }


    /**
     * 解析金额
     *
     * @param amount
     * @return
     */
    public int parseAmount(String amount) {
        if (amount.contains("-")) {
            amount = amount.trim().replace("-", "");
        }

        BigDecimal bigDecimal = new BigDecimal(amount);
        BigDecimal multiply = bigDecimal.multiply(new BigDecimal(100));
        return multiply.intValue();
    }


    /**
     * 下载七牛对账文件到本地
     * @return
     */
    public Boolean qiniuDownloadSave(String fileName , String hospitalName){

        //从七牛获取文件到本地
        String bucketURL = yaml.getProperty(Alipay.QINIU_CHECK_ACCTOUNT_DOWNLOAD_URL);
        String path = yaml.getProperty(Config.CONFIG_PAY_WECHAT_CHECK_ACCOUNT_PATH);
        String url = QiniuService.download(fileName, path, bucketURL);

        String filePath = path + fileName;
        logger.info(hospitalName + "---yaml property bucketURL:" + bucketURL + ",path:" + path);
        logger.info(hospitalName + "---Check_Account_File_Save_Path:" + filePath);

        boolean flag = false;
        if(StringUtils.isNotBlank(url)){
            int count=0;
            int repeatCount=5;
            while (!flag){
                flag = HttpUtils.httpDownload(url, filePath);
                count++;
                if(count>repeatCount){
                    break;
                }
            }
        }

        return flag;
    }


    /**
     * 账单入库
     *
     * @param sourceFiles
     * @return
     */
    public int addSourceFile(List<PaymentCheckSourceFile> sourceFiles, String hospitalId ,String hospitalName) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        long exbeginTime = new Date().getTime() / 1000;
        logger.info("<<<<< batchInsert.beginTime:" + exbeginTime);
        int count = 0;
        if (sourceFiles.size() > 0) {
            List<PaymentCheckSourceFile> checkList = new ArrayList<PaymentCheckSourceFile>();
            PaymentCheckSourceFile sourceFile = new PaymentCheckSourceFile();
            try {
                sourceFile.setOrgId(hospitalId);
                sourceFile.setBeginImportTime(df.format(new Date()));
                sourceFile.setEndImportTime(df.format(new Date()));
                List<PaymentCheckSourceFile> payList = paymentCheckSourceFileDao.select(sourceFile);
                logger.info(hospitalName + "_获取到已存在第三方账单表数据条数："+ payList.size());

                //去重逻辑
                Map<String, PaymentCheckSourceFile> exSourcesMap = new HashMap<String, PaymentCheckSourceFile>();
                for (PaymentCheckSourceFile pcs : payList) {
                    exSourcesMap.put(pcs.getOrderNo(), pcs);
                }

                for (PaymentCheckSourceFile data : sourceFiles) {
                    if(!exSourcesMap.containsKey(data.getOrderNo())){
                        checkList.add(data);
                    }else{
                        PaymentCheckSourceFile paySource = exSourcesMap.get(data.getOrderNo());
                        if(!data.getPayStatus().equals(paySource.getPayStatus())){
                            checkList.add(data);
                        }
                    }
                }

                logger.info("去重后获取到账单条数："+ checkList.size());

                //过滤多家医院使用一个账户，只入库该家医院订单
                List<PaymentCheckSourceFile> insertList = new ArrayList<PaymentCheckSourceFile>();
                for (PaymentCheckSourceFile paymentCheckSourceFile : checkList) {
                    if(hospitalId.equals(paymentCheckSourceFile.getOrgId())){
                        insertList.add(paymentCheckSourceFile);
                    }
                }

                //入库逻辑
                if (checkList.size() > 0) {
                    logger.info(hospitalId + "_微信对账单获取成功入库笔数：" + insertList.size());
                    paymentCheckSourceFileDao.batchInsert(insertList);
                }
                count = checkList.size();
                logger.info("<<<<< batchInsert.endTime:" + (new Date().getTime() / 1000 - exbeginTime));
            } catch (Exception e) {
            	logger.error("保存数据失败", e);
                logger.error("[AlipayPaymentCheckSourceFileServiceImpl.addSourceFile]", e);
            }
        }
        return count;

    }


    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        WechatPaymentServiceImpl bean = applicationContext.getBean(WechatPaymentServiceImpl.class);

        PaymentCheckSourceFile pc = new PaymentCheckSourceFile();
        pc.setOrderNo("Y520170220144010119");
        pc.setPayStatus((short) 1);

        PaymentCheckSourceFile pc1 = new PaymentCheckSourceFile();
        pc1.setOrderNo("Y5201702201451101110");
        pc1.setPayStatus((short) 2);

        PaymentCheckSourceFile pc2 = new PaymentCheckSourceFile();
        pc2.setOrderNo("Y5201702201451101111");
        pc2.setPayStatus((short) 2);

        List<PaymentCheckSourceFile> sources = new ArrayList<PaymentCheckSourceFile>();
        sources.add(pc);
        sources.add(pc1);
        sources.add(pc2);

//        int z = bean.addSourceFile(sources, "0b0ed0499a8911e6951000163e00175d");
//        System.out.println(z);
    }
}
